package com.emily.test.controller;

import com.alibaba.fastjson.JSONObject;
import com.emily.test.constant.ReturnValueConstants;
import com.emily.test.controller.result.ResponseResult;
import com.emily.test.model.DTo;
import com.emily.test.model.TCompany;
import com.emily.test.model.TUser;
import com.emily.test.service.RedisService;
import com.emily.test.service.TCompanyService;
import com.emily.test.service.TUserService;
import com.emily.test.utils.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;


import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.*;

/**
 * 登录controller
 *
 * @author 田庆新
 */
@RestController
@CrossOrigin(origins = "*", maxAge = 3600)
@RequestMapping(value = "loginController")
@Api(value = "LoginControllerApi", description = "LoginController接口类", position = 1, produces = MediaType.APPLICATION_JSON_VALUE)
public class LoginController {

    private Logger logger = LoggerFactory.getLogger(LoginController.class);


    /*
     注入redis操作实例，
     可以用以下两种方式进行注入，
     第一种可在添加RedisConfig类之后直接注入。
     若进行第二种方式则需要补全RedisService
     */

//    @Resource
//    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private RedisService redisService;


    @Autowired
    private TCompanyService tCompanyService;

    @Autowired
    private TUserService tUserService;

    @ApiOperation(value = "用户登录接口", notes = "用户登录接口")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "loginName", value = "登录名", required = true),
            @ApiImplicitParam(name = "password", value = "登录密码", required = true)
    })
    @PostMapping(value = "userLogin")
    @ResponseBody
    public ResponseResult userLogin(@RequestBody JSONObject jsonObject,
                                    HttpServletRequest request, HttpServletResponse response) {
        String loginName = jsonObject.getString("loginName");
        String password = jsonObject.getString("password");
        DTo dto = new DTo();
        if (ConstentUtil.isEmpty(loginName)) {
            dto.setIsLogin("false");
            logger.error("登录失败，用户名为空");
            return ResponseResult.fail(ReturnValueConstants.LOGIN_FAILURE + "用户名" + ReturnValueConstants.IS_NOT_ALLOW_NULL);
        }
        if (ConstentUtil.isEmpty(password)) {
            dto.setIsLogin("false");
            logger.error("登录失败，密码为空");
            return ResponseResult.fail(ReturnValueConstants.LOGIN_FAILURE + "密码" + ReturnValueConstants.IS_NOT_ALLOW_NULL);
        }
        try {

//            TCompany result =tCompanyService.selectCompanyInfoByLoginName(loginName);

//            TUser userInfo=tUserService.selectUserInfoByLoginName(loginName);
            TUser tu = new TUser();
            tu.setLoginName(loginName);
            Map<String, Object> userInfoMap = tUserService.getUserAllInfoMap(tu);

            if (ConstentUtil.isEmpty(userInfoMap)) {
                dto.setIsLogin("false");
                logger.error("登录失败，登录名不存在");
                return ResponseResult.fail(ReturnValueConstants.LOGIN_FAILURE + "登录名" + ReturnValueConstants.IS_NOT_EXIT);
            }
            if (userInfoMap.get("state").equals(0)) {
                logger.error("登录失败，该用户被禁用");
                return ResponseResult.fail(ReturnValueConstants.LOGIN_FAILURE + "登录名被禁用");
            }
            //比较密码是否匹配
            String passwordInDb = (String) userInfoMap.get("password");
            boolean isMatch = MD5Utils.validPassword(password, passwordInDb);
            if (!isMatch) {
                dto.setIsLogin("false");
                return ResponseResult.fail("密码" + ReturnValueConstants.IS_NOT_MATCH);
            }

            Integer userId = (Integer) userInfoMap.get("userId");
            //获取用户的角色信息
            List<Map<String, Object>> roleMapForUser = tUserService.getRolesByUserId(userId);
            userInfoMap.put("userRoleList", roleMapForUser);

            //查询用户所拥有的资源
            List<Map<String,Object>> resourceList =new ArrayList<Map<String,Object>>();
            String companyCode = (String) userInfoMap.get("companyCode");
            Integer companyId =null;
            if(!ConstentUtil.isEmpty(companyCode)){
                Map<String,Object> companyInfo=  tUserService.getCompanyInfoByCode(companyCode);
                if(!ConstentUtil.isEmpty(companyInfo)){
                    companyId= (Integer) companyInfo.get("id");
                }
            }
            resourceList=tUserService.getResourceInfoByCompanyIdList(companyId);

            //根据用户的角色信息获取用户所拥有的菜单信息
            List<Integer> roleIdsList=new ArrayList<Integer>();
            if(!ConstentUtil.isEmpty(roleMapForUser)){
                for(Map<String,Object> map:roleMapForUser){
                    Integer roleId= (Integer) map.get("roleId");
                    roleIdsList.add(roleId);
                }
            }
            if(ConstentUtil.isEmpty(roleIdsList)){
                return ResponseResult.fail("请联系管理员配置您的个人权限!");
            }
            List<Map<String,Object>> menuMapList=tUserService.getMenuListByRoleIds(roleIdsList);
            menuMapList=ConstentUtil.removeRepeatMap(menuMapList,"menuId");
            //将菜单添加到相应系统下
            if(!ConstentUtil.isEmpty(menuMapList) && !ConstentUtil.isEmpty(resourceList)){
                for(Map<String,Object> resourceMap : resourceList){
                    List<Map<String,Object>> resMenuList=new ArrayList<Map<String,Object>>();
                    Integer resId= (Integer) resourceMap.get("id");
                     for(Map<String,Object>  menuMap : menuMapList){
                         Integer resourceId= (Integer) menuMap.get("resourceId");
                         if(resourceId.equals(resId)){
                              resMenuList.add(menuMap);
                         }
                     }
                     resourceMap.put("menuList",resMenuList);
                }
            }
            userInfoMap.put("resourceList",resourceList);
            //生成token字符串，并以此为标识key将登陆对象的ID存储到redis中,并将token放到cookie里面
            String token = TokenUtil.generateToken(loginName);
            System.out.println(CookieUtils.getCookieMap(request));
            CookieUtils.updateCookieByName(request, response, "token", token);
            dto.setIsLogin("true");
            dto.setToken(token);
            dto.setTokenCreatedTime(System.currentTimeMillis());
            dto.setTokenExpiryTime(System.currentTimeMillis() + 2 * 60 * 60 * 1000);
            dto.setUserMap(userInfoMap);
            redisService.set(token, userInfoMap,60*60);
            //将用户的信息放入dto对象中
            logger.info("token={},userInfo={}", token, userInfoMap);
            System.out.println("redistoken================" + redisService.get(token));
            logger.info(ReturnValueConstants.LOGIN_SUCCESS + "登录名={}", loginName);
            return ResponseResult.success(dto);
        } catch (Exception e) {
            logger.error(ReturnValueConstants.LOGIN_FAILURE, e);
            e.printStackTrace();
            return ResponseResult.fail("登录失败");
        }
    }

    @Value("${server.port}")
    private String serverPort;

    @GetMapping("/session")
    public Object getSession(HttpServletRequest request) {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("SessionId", request.getSession().getId());
        map.put("ServerPort", "服务端口号为 " + serverPort);
        return map;
    }

    @GetMapping("/getCookie")
    public Object getCookie(HttpServletRequest request, HttpServletResponse response) {

        return CookieUtils.getCookieValue(request, "token");
    }

    @ApiOperation(value = "用户登出接口", notes = "用户登出接口")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "token", value = "token", required = true),
    })
    @PostMapping(value = "signOut")
    @ResponseBody
    public ResponseResult signOut(@RequestBody JSONObject jsonObject) {
        try {
            String token = jsonObject.getString("token");
            redisService.del(token);
            return ResponseResult.success("登出成功");
        } catch (Exception e) {
            logger.error(ReturnValueConstants.LOGIN_FAILURE, e);
            e.printStackTrace();
            return ResponseResult.fail("登出失败");
        }
    }
}
